#############################################################################
# FileManager plugin for Rhythmbox
# Copyright (C) 2008 Dmitry Teslenko
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
#############################################################################

import os
import shutil
import rb
import rhythmdb
import gtk
import ConfigParser as cp
from urlparse import urlparse
from urllib import url2pathname

import filemanager_widgets as fw

UI_XML = '''
<ui>
  <menubar name="MenuBar">
	<menu name="ToolsMenu" action="Tools">
      <separator/>
	  <menuitem name="CopyFiles" action="CopyFiles"/>
	  <menuitem name="DeleteFiles" action="DeleteFiles"/>
	</menu>
  </menubar>
  <popup name="BrowserSourceViewPopup">
	  <separator/>
	  <menuitem name="CopyFiles" action="CopyFiles"/>
	  <menuitem name="DeleteFiles" action="DeleteFiles"/>
  </popup>
</ui>
'''

class FileManagerPlugin(rb.Plugin):
	def __init__(self):
		rb.Plugin.__init__(self)
		self.__config_path = os.path.expanduser('~/.rb_filemanager')
		self.__config = cp.ConfigParser()
		self.__config.read(self.__config_path)
		if not self.__config.has_section('General'):
			self.__config.add_section('General')
			self.__update_config()

		self.__item_list = []
		return

	def activate(self, shell):
		self.__shell = shell

		self.__create_ui()
		return

	def deactivate(self, shell):
		self.__destroy_ui()

		self.__shell = None
		return
	
	def __create_ui(self):
		self.__copy_action = gtk.Action('CopyFiles', 
			_('_Copy selected songs to folder'), 
			_('Copies selected songs to the specified folder or device'),
			'rb-copy-files')
		self.__copy_action.connect('activate', self.copy_files)
		self.__delete_action = gtk.Action('DeleteFiles', 
			_('_Remove selected songs'), 
			_('Removes selected songs from filesystem'),
			'rb-delete-files')
		self.__delete_action.connect('activate', self.delete_files)

		self.__action_group = gtk.ActionGroup('FileManagerActions')
		self.__action_group.add_action_with_accel(self.__copy_action, 
			'<control>M')
		self.__action_group.add_action_with_accel(self.__delete_action, 
			'<control>V')

		um = self.__shell.get_ui_manager()
		um.insert_action_group(self.__action_group, 0)
		self.__ui = um.add_ui_from_string(UI_XML)
		um.ensure_update()
		return

	def __destroy_ui(self):
		um = self.__shell.get_ui_manager()
		um.remove_ui(self.__ui)

		um.remove_action_group(self.__action_group)

		self.__action_group = None
		self.__copy_action = None

		return


	def __get_item_path(self, index, folder, mask):
		try:
			item = self.__item_list[index]
			s = ''
			if item:
				tmp, ext = os.path.splitext(item.path)
				s = mask

				s = s.replace('%a', item.artist)
				s = s.replace('%t', item.title)
				s = s.replace('%b', item.album)
				s = s.replace('%s', str(index + 1))
				
				try:
					import pytils
					s = pytils.translit.translify(s.decode('utf-8'))
				except:
					pass

				s = s.replace('\\', '')
				s = s.replace('/', '')
				s = s.replace('*', '')
				s = s.replace('?', '')
				s = s.replace('"', '')
				s = s.replace('<', '')
				s = s.replace('>', '')
				s = s.replace('|', '')
				s = s.replace(':', '')

				s = '%s/%s' % (folder, s)
				s += ext
			return s
		except IndexError, e:
			pass
		return ''

	def copy_files(self, action):
		self.__update_item_list()
		
		try:
			folder_path = self.__config.get('General', 'CopyFolder')
		except cp.NoOptionError, e:
			folder_path = ''
		try:
			mask = self.__config.get('General', 'CopyMask')
		except cp.NoOptionError, e:
			mask = '%a_%b_%t'

		fc = fw.SelectFolderDialog('Select target folder')
		fc.set_mask(mask)
		fc.set_folder_path(folder_path)
		fc.set_get_caption_func(self.__get_item_path)
		
		r = fc.run() 
		fc.hide()
		if r == gtk.RESPONSE_ACCEPT:
#This shows dialog
			folder_path = fc.get_folder_path()
			mask = fc.get_mask()

			self.__config.set('General', 'CopyFolder', folder_path)
			self.__config.set('General', 'CopyMask', mask)
			self.__update_config()
			
			source = self.__shell.get_property('selected_source')
			db = self.__shell.get_property('db')
			entry = rb.Source.get_entry_view(source)
			selected = entry.get_selected_entries()

			reserved_targets = []
			path_tuples = []
			
			idx = 0
			for item in self.__item_list:
				target_path = self.__get_item_path(idx, folder_path, mask)
				target_path, ext = os.path.splitext(target_path)
				suffix = ''
				i = 0
				while (target_path + suffix + ext 
					in reserved_targets) or os.path.exists(target_path 
					+ suffix + ext):
					suffix = '(%i)' % i
					i += 1
				
				path_tuples.append((item.path, target_path + suffix
					+ ext))

				idx += 1
		
			for s, t in path_tuples:
				shutil.copyfile(s, t)
		fc.destroy()
		return

	def __update_item_list(self):
		self.__item_list = []

		source = self.__shell.get_property('selected_source')
		db = self.__shell.get_property('db')
		entry = rb.Source.get_entry_view(source)
		selected = entry.get_selected_entries()

		reserved_targets = []
		path_tuples = []
		for entry in selected:
			source_path = url2pathname(urlparse(
				entry.get_playback_uri())[2])
			if os.path.isfile(source_path):
				i = ItemInfo()
				i.path = source_path
				i.title = db.entry_get(entry, rhythmdb.PROP_TITLE)
				if not i.title:
					i.title = 'Unknown'
				i.album = db.entry_get(entry, rhythmdb.PROP_ALBUM)
				if not i.album:
					i.album = 'Unknown'
				i.artist = db.entry_get(entry, rhythmdb.PROP_ARTIST)
				if not i.artist:
					i.artist = 'Unknown'
				self.__item_list.append(i)
		return

	def delete_files(self, action):
		self.__update_item_list()

		file_path_list = []

		for item in self.__item_list:
			file_path_list.append(item.path)

		if not file_path_list:
			return

		qd = gtk.MessageDialog(flags = gtk.DIALOG_MODAL, 
			type = gtk.MESSAGE_QUESTION, 
			buttons = gtk.BUTTONS_NONE,
			message_format = 'Are you sure you want to delete %i file(s)?'
				% len(file_path_list))
		qd.add_buttons(gtk.STOCK_NO, gtk.RESPONSE_REJECT,
			gtk.STOCK_YES, gtk.RESPONSE_ACCEPT)
		r = qd.run() 
		qd.destroy()
		if r == gtk.RESPONSE_ACCEPT:
			for file_path in file_path_list:
				os.remove(file_path)
		return

	def __update_config(self):
		f = open(self.__config_path, 'w')
		try:
			self.__config.write(f)
		finally:
			f.close()
		return

class ItemInfo:
	def __init__(self):
		path = ''
		artist = ''
		title = ''
		album = '' 
		return
